/**
 * 
 */
package com.ms.game.invitefriend;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken;
import com.ms.game.characterInfo.CharacterInfoProcessor;
import com.ms.game.common.container.GameLimitInfo;
import com.ms.game.common.container.LevelInfoBinUtil;
import com.ms.game.invitefriend.async.GetDistributorInviteCodeAsync;
import com.ms.game.invitefriend.async.GetDownlineCommInfoAsync;
import com.ms.game.invitefriend.async.GetInviteCodeDCLAsync;
import com.ms.game.invitefriend.async.GetSubDistributorsInfoAsync;
import com.ms.game.invitefriend.async.ModifySubDistributorCommSettingAsync;
import com.ms.game.invitefriend.bin.InviteCodeInfo;
import com.ms.game.invitefriend.bin.InviteCodeRewardBinUtil;
import com.ms.game.invitefriend.bin.InviteCodeType;
import com.ms.game.invitefriend.bin.ItemInfo;
import com.ms.game.invitefriend.bin.RewardDetail;
import com.ms.game.invitefriend.bin.UplineInviteRewardInfo;
import com.ms.game.invitefriend.db.DistributorInviteCodeDAO;
import com.ms.game.invitefriend.db.DistributorInviteCodesModel;
import com.ms.game.invitefriend.db.DistributorsModel;
import com.ms.game.invitefriend.db.InviteCodeGroupModel;
import com.ms.game.invitefriend.db.InviteCodeModel;
import com.ms.game.invitefriend.db.InviteFriendDAO;
import com.ms.game.invitefriend.db.SubDistributorsModel;
import com.ms.game.invitefriend.message.AddInviteCodeData;
import com.ms.game.invitefriend.message.CGetDownlineCommInfoRequest;
import com.ms.game.invitefriend.message.CGetSubDistributorsInfoRequest;
import com.ms.game.invitefriend.message.CModifySubDistributorCommSetting;
import com.ms.game.invitefriend.message.SGetDownlineCommInfoResponse;
import com.ms.game.invitefriend.message.SGetInviteCodeResponse;
import com.ms.game.invitefriend.message.SGetSubDistributorsInfoResponse;
import com.ms.game.invitefriend.message.SModifySubDistributorCommSettingResponse;
import com.ms.game.itembox.ChangeItemLister;
import com.ms.game.itembox.ItemBox;
import com.ms.game.itembox.ItemChangeParam;
import com.ms.game.itembox.ItemChangeWay;
import com.ms.game.itembox.container.ItemBasic;
import com.ms.game.itembox.db.ItemChangeProcessData;
import com.ms.game.itembox.db.ItemDAO;
import com.ms.game.itembox.db.PlayerItemChangeLogModel;
import com.ms.game.lobby.GameLobbyModule;
import com.ms.player.Player;
import com.ms.player.PlayerIdentityType;
import com.ms.player.UpdateAttributeList;
import com.ms.service.error.ErrorCode;
import com.ms.service.module.account.Account;
import com.xpec.c4.db.dao.PlayerDAO;
import com.xpec.c4.db.model.PlayerModel;
import com.xpec.c4.game.common.Helper;
import com.xpec.c4.game.datamanager.agent.money.CoinType;
import com.xpec.c4.game.datamanager.agent.money.MoneyChangeWay;
import com.xpec.c4.game.time.TimeSys;
import com.xpec.c4.game.utility.GUID;
import com.xpec.c4.game.utility.GUIDFactory;
import com.xpec.c4.game.utility.GUIDType;
import com.xpec.c4.game.utility.GameUtility;
import com.xpec.c4.message.MessageTypes;
import com.xpec.c4.service.group.transportlayer.GroupMessage;
import com.xpec.c4.service.message.MessageAction;
import com.xpec.c4.service.module.BasicServiceModule;
import com.xpec.c4.service.module.ConsistentGroupName;
import com.xpec.c4.service.module.ModuleName;
import com.xpec.c4.service.module.ServerProperties;
import com.xpec.c4.service.module.common.ItemInfoManager;
import com.xpec.c4.service.module.common.PlayerCommonInfoManager;
import com.xpec.c4.service.module.datacenter.player.db.PlayerMoneyChangeLogModel;

/**
 * @author TW15010
 * 
 */
public class InviteCodeProcessor {
	/**
	 * 識別經銷商邀請碼的字母
	 */
	public static final char DISTRIBUTOR_INVITE_CODE_IDENTIFY = 'E';
	

	
	
	/** 此次邀請碼獎勵的 order id */
	private String orderId;

	/** 金錢的 log model */
	private PlayerMoneyChangeLogModel moneyLogModel;
	
	private Gson gson = new Gson();

	/** 道具的 log model */
	private ArrayList<PlayerItemChangeLogModel> itemLogModelList = new ArrayList<PlayerItemChangeLogModel>();

	public Gson getGson() {
		return gson;
	}
	
	public ArrayList<PlayerItemChangeLogModel> getItemLogModelList() {
		return itemLogModelList;
	}
	

	public static InviteCodeType getInviteCodeType(String inviteCode) {
		if(!GameUtility.isHaveString(inviteCode)){
			return null;
		}
		
		if(inviteCode.indexOf(DISTRIBUTOR_INVITE_CODE_IDENTIFY) >= 0){
			//經銷商邀請碼
			return InviteCodeType.DISTRIBUTOR_INVITE_CODE;
		}
		
		InviteCodeModel inviteCodeModel = InviteFriendDAO.getInviteCodeModel(inviteCode);
		if(inviteCodeModel == null){
			return null;
		}
		
		return inviteCodeModel.getType();
	}
	
	/**
	 * 給角色增加邀請碼 
	 * 目前是送去抽傭module 做
	 * @param playerId
	 */
	public static void addInviteCodeToPlayer(String playerId){
		// 先檢查是不是已經有邀請碼了
		ArrayList<InviteCodeModel> models = InviteFriendDAO.getInviteCodeModelsByPlayerId(playerId);
		if(GameUtility.getArrayListSize(models) > 0){
			return;
		}
		
		AddInviteCodeData addInviteCodeData = new AddInviteCodeData();
		addInviteCodeData.setPlayerId(playerId);
		addInviteCodeData.setUpperLimit(1);
		addInviteCodeData.setInviteCodeTypeString(InviteCodeType.NEW_INVITE_CODE.toString());
		GroupMessage msg = new GroupMessage();
		msg.setMessageType(MessageTypes.S_ADD_INVITE_CODE_TO_PLAYER);
		msg.setMessageContent(addInviteCodeData);
		msg.setDestModuleID(ModuleName.COMMISON);
		MessageAction.sendGroupMessage(msg);
		
	}
	
	/**
	 * 檢查是否符合使用邀請碼的條件
	 * 
	 * @param codeType
	 *            邀請碼類型
	 * @param player
	 *            player data
	 * @param account
	 *            account data
	 * @return 結果代碼 {@link ErrorCode} (8xxxx)
	 */
	public int checkPlayerData (InviteCodeType codeType, Player player, InviteCodeModel inviteCodeModel,DistributorInviteCodesModel distributorInviteCodesModel ,InviteCodeInfo codeInfo ,Account account) {
		if (player == null || account == null) {
			return ErrorCode.INVALID_PARAM;
		}
		
		// account 已經有記錄邀請碼，表示曾經輸入過
		if (GameUtility.isHaveString(account.getUplineCode())) {
			return ErrorCode.ACCOUNT_INVITE_CODE_CANT_USE_SECOND_INVITE_CODE_IN_SAME_ACCOUNT;
		}
		
		// 有限定只有帳號下第一隻角色能使用邀請碼
		if (codeInfo.isFirstPlayerOnly()) {
			if (account.getCreatedPlayerCount() >= 1) {
				return ErrorCode.ACCOUNT_INVITE_CODE_ONLY_FIRST_PLAYER_CAN_USE_INVITE_CODE;
			}
		}
		
		if(codeType == InviteCodeType.DISTRIBUTOR_INVITE_CODE){
			//經銷商邀請碼的檢查
			
			//檢查是否被使用
			if(distributorInviteCodesModel.isUsed()) {
				return ErrorCode.ACCOUNT_INVITE_CODE_HAD_BEEN_USED;
			}
			
			//先檢查經銷商
			String distributorGuid = distributorInviteCodesModel.getDistributorGuid();
			
			PlayerModel distributorPlayer = PlayerDAO.loadPlayerModelByGuid(GUID.parseUUID(distributorGuid));
			if(distributorPlayer == null) {
				return ErrorCode.ACCOUNT_INVITE_CODE_NOT_EXIST;
			}
			
			DistributorsModel distributorsModel = DistributorInviteCodeDAO.getDistributorModelByGUID(distributorGuid);
			if(distributorsModel == null){
				return ErrorCode.ACCOUNT_INVITE_CODE_NOT_EXIST;
			}
			
			if(!distributorsModel.isEffective()){
				return ErrorCode.ACCOUNT_INVITE_CODE_NOT_EXIST;
			}
			
			if(distributorInviteCodesModel.getIdentifyType() == PlayerIdentityType.DISTRIBUTOR){
				if (distributorGuid.equals(player.getAccountId().toString())) {
					// 邀請碼不能是自己帳號下角色的
					return ErrorCode.ACCOUNT_INVITE_CODE_CANT_USE_SELF_ACCOUNT_PLAYER_CODE;
				}

				player.setUplineId(distributorGuid);
				player.setPlayerIdentityType(PlayerIdentityType.SUB_DISTRIBUTOR);
				
			}else if(distributorInviteCodesModel.getIdentifyType() == PlayerIdentityType.SUB_DISTRIBUTOR){
				//子經銷商檢查
				String subDistributorGuid = distributorInviteCodesModel.getSubDistributorGuid();
				
				PlayerModel subDistributorPlayer = PlayerDAO.loadPlayerModelByGuid(GUID.parseUUID(subDistributorGuid));
				if(subDistributorPlayer == null) {
					return ErrorCode.ACCOUNT_INVITE_CODE_NOT_EXIST;
				}
				
				if (subDistributorGuid.equals(player.getAccountId().toString())) {
					// 邀請碼不能是自己帳號下角色的
					return ErrorCode.ACCOUNT_INVITE_CODE_CANT_USE_SELF_ACCOUNT_PLAYER_CODE;
				}
				
				player.setUplineId(subDistributorGuid);
				player.setPlayerIdentityType(PlayerIdentityType.DOWNLINE);
			}
		}else{
			//其他邀請碼的檢查
			
			//檢查是否被使用過
			if(inviteCodeModel.isSingleUse() && inviteCodeModel.isHaveBeenUsed()){
				return ErrorCode.ACCOUNT_INVITE_CODE_HAD_BEEN_USED;
			}
			
			//檢查是否過期
			Long expiration = inviteCodeModel.getExpiration();
			if(expiration != null && expiration.longValue() > 0l){
				if (TimeSys.currentTimeMills() > (long)expiration) {
					return ErrorCode.ACCOUNT_INVITE_CODE_OUT_OF_DATE;
				}
			}
			
			//檢查是否已經作廢
			if(codeType == InviteCodeType.ACTIVITY_SHARE_INVITE_CODE){
				if(inviteCodeModel.isInvalid()){
					return ErrorCode.ACCOUNT_INVITE_CODE_IS_INVALID;
				}
			}
			
			if (codeType != InviteCodeType.ACTIVITY_INVITE_CODE && codeType != InviteCodeType.ACTIVITY_SHARE_INVITE_CODE) {
				// 以下檢查 除了活動邀請碼 目前所有邀請碼都要進來做檢查

				// 取得擁有這個邀請碼的玩家資料
				PlayerModel uplinePlayerModel = PlayerDAO.loadPlayerModelByInviteCode(player.getUplineCode());
				if (uplinePlayerModel == null) {
					// 找不到
					return ErrorCode.ACCOUNT_INVITE_CODE_NOT_EXIST;
				}

				if (uplinePlayerModel.getAccountId().equals(player.getAccountId().toString())) {
					// 邀請碼不能是自己帳號下角色的
					return ErrorCode.ACCOUNT_INVITE_CODE_CANT_USE_SELF_ACCOUNT_PLAYER_CODE;
				}

				// 檢查沒問題 把上線ID加進去欄位裡
				player.setUplineId(uplinePlayerModel.getGuid());
			}
		}
		

		return ErrorCode.SUCCESS;
	}

	/**
	 * 將邀請碼獎勵的錢加到角色上
	 * 
	 * @param player
	 *            角色
	 * @param type
	 *            哪種錢 {@link CoinType}
	 * @param value
	 *            增加的值
	 */
	private void coinProc(Player player, CoinType type, ArrayList<String> valueList) {
		if (player == null || valueList == null) {
			return;
		}

		int cnt = valueList.size();
		if (cnt == 0) {
			return;
		}

		// 隨機選一個金額
		BigDecimal value = new BigDecimal(GameUtility.getRandomElement(valueList));

		// 加到角色身上
		BigDecimal curCoin = player.getCoin(type);
		BigDecimal newCoin = Helper.add(curCoin, value);
		player.setCoin(type, newCoin);

		// 產生 log model
		if (moneyLogModel == null) {
			moneyLogModel = new PlayerMoneyChangeLogModel();
			moneyLogModel.setOrderId(getOrderId());
			moneyLogModel.setAccountId(player.getAccountId().toString());
			moneyLogModel.setPlayerId(player.getGuid().toString());
			moneyLogModel.setPlayerName(player.getName());
			moneyLogModel.setUserType(player.getUserType());
			moneyLogModel.setGameHallId(ConsistentGroupName.lookUpLoginModule(player.getAccountId(), player.isRobot()));
			moneyLogModel.setGameHallName("");
			moneyLogModel.setChangeWay(MoneyChangeWay.ADD_INVITE_CODE.getId());
			moneyLogModel.setChangeWayDesc(MoneyChangeWay.ADD_INVITE_CODE.getDesc());
		}

		switch (type) {
		case GOLD:
			moneyLogModel.setGoldChangeValue(value);
			moneyLogModel.setGoldBeforeChange(curCoin);
			moneyLogModel.setGoldAfterChange(newCoin);
			break;
		case LUCKY:
			moneyLogModel.setLuckyChangeValue(value);
			moneyLogModel.setLuckyBeforeChange(curCoin);
			moneyLogModel.setLuckyAfterChange(newCoin);
			break;
		default:
			break;
		}
	}

	/**
	 * 將邀請碼獎勵的道具加到角色身上
	 * 
	 * @param player
	 *            player data
	 * @param itemPackList
	 *            道具包清單 {@link RewardDetail#getItemPackList()}
	 */
	private void itemProc(Player player, ArrayList<ArrayList<ItemInfo>> itemPackList) {
		if (player == null || itemPackList == null) {
			return;
		}

		int cnt = itemPackList.size();
		if (cnt == 0) {
			return;
		}

		// 隨機選一個道具包
		ArrayList<ItemInfo> itemList = GameUtility.getRandomElement(itemPackList);

		// 將道具包內的道具一個一個加到 player 身上
		ItemBox itemBox = player.getItemBox();
		if (itemBox == null) {
			itemBox = new ItemBox();
			player.setItemBox(itemBox);
		}
	
		// 要給的東西加入異動清單
		ChangeItemLister itemLister = new ChangeItemLister();
		for (ItemInfo item : itemList) {
			ItemBasic itemBasic = ItemInfoManager.getInstance().getItemBox().get(item.getItemId());
			itemLister.addItem(null, item.getItemId(), item.getCount(), itemBasic.getItemRefineLevel());
		}

		// 產生道具異動參數資料結構
		ItemChangeParam param = new ItemChangeParam();
		param.setOrderId(GUID.parseUUID(getOrderId()));
		param.setChangeWay(ItemChangeWay.ADD_INVITE_CODE);
		param.setChangeItemLister(itemLister);
		param.setGameHallId(ConsistentGroupName.lookUpLoginModule(player.getAccountId(), player.isRobot()));
		param.setGameHallName("");
		param.setAccountId(player.getAccountId());
		param.setPlayerId(player.getGuid());
		param.setPlayerName(player.getNameWithNumber());
		param.setUserType(player.getUserType());
		param.setTargetId(null);
		param.setTargetName(null);
		param.setSrcModuleId(player.getZoneId());

		ItemChangeProcessData itemChangeProcData = ItemDAO.changeItemVerify(param);
		if (param.getResult() == ErrorCode.SUCCESS) {
			UpdateAttributeList updateAttributeList = new UpdateAttributeList();
			ItemDAO.changeItemApply(param, itemChangeProcData, updateAttributeList);
			ArrayList<PlayerItemChangeLogModel> logList = param.getLogModelList();
			itemLogModelList.addAll(logList);
			UpdateAttributeList.applyUpdateListToPlayer(updateAttributeList.getUpdateList(), player);
		}
	}

	/**
	 * 將邀請碼獎勵加到角色身上
	 * 
	 * @param codeType
	 *            邀請碼類型
	 * @param player
	 *            player data
	 * @return {@link ErrorCode} (8xxxx)
	 */
	public int applyReward(InviteCodeType codeType, Player player , InviteCodeGroupModel groupModel, InviteCodeInfo codeInfo) {
		if (codeType == null || player == null) {
			return ErrorCode.INVALID_PARAM;
		}
		
		UplineInviteRewardInfo uplineInviteRewardInfo = InviteCodeRewardBinUtil.getuplinInviteRewardInfo(codeType);

		player.setCanMakeCommission(uplineInviteRewardInfo.isCanMakeCommission());
		
		// 獎勵數據
		RewardDetail rewardDetail = codeInfo.getRewardDeteil();

		if(rewardDetail != null){
			// 正式會員資格
			if (rewardDetail.isBecomeFormalMember()) {
				// 會員等級
				player.setLevel(1);

				// 會員經驗值
				player.setExp(LevelInfoBinUtil.getExpByLevel(0, player.getLevel()));
			}

			if(groupModel != null){				
				//檢查C幣
				if(GameUtility.isHaveString(groupModel.getGoldCoins())){
					JsonArray coinString = gson.fromJson(groupModel.getGoldCoins(), JsonElement.class).getAsJsonArray();
					ArrayList<String> goldCoins = gson.fromJson(coinString, new TypeToken<ArrayList<String>>(){}.getType());
					coinProc(player, CoinType.GOLD, goldCoins);
				}
				
				//檢查道具
				if(GameUtility.isHaveString(groupModel.getItems())){
					JsonArray itemString = gson.fromJson(groupModel.getItems(), JsonElement.class).getAsJsonArray();
					ArrayList<ArrayList<ItemInfo>> items = gson.fromJson(itemString, new TypeToken<ArrayList<ArrayList<ItemInfo>>>(){}.getType());
					itemProc(player, items);
				}
			}else{
				if (rewardDetail.getGoldCoinList() != null && rewardDetail.getGoldCoinList().size() > 0) {
					// 金幣
					coinProc(player, CoinType.GOLD, rewardDetail.getGoldCoinList());
				}

				if (rewardDetail.getItemPackList() != null && rewardDetail.getItemPackList().size() > 0) {
					// 道具
					itemProc(player, rewardDetail.getItemPackList());
				}

				if (rewardDetail.getLuckyCoinList() != null && rewardDetail.getLuckyCoinList().size() > 0) {
					// 幸運金
					coinProc(player, CoinType.LUCKY, rewardDetail.getLuckyCoinList());
				}
			}
		}

		return ErrorCode.SUCCESS;
	}

	/**
	 * 寫入 log
	 */
	public void saveLog(BasicServiceModule currentModule) {
		if (currentModule == null) {
			return;
		}

		// 寫入錢的 log
		if (moneyLogModel != null) {
			if (ServerProperties.isNeedSaveMoneyChangeLog(moneyLogModel)) {
				currentModule.saveDbLog(moneyLogModel);
			}
			currentModule.saveDbLog(CharacterInfoProcessor.convertDailyExchange(moneyLogModel));
		}

		// 寫入道具的 log
		for (PlayerItemChangeLogModel logModel : itemLogModelList) {
			currentModule.saveDbLog(logModel);
		}
	}

	/**
	 * 產生並取得此次獎勵 log 的 orderId
	 * 
	 * @return order id
	 */
	private String getOrderId() {
		if (orderId == null) {
			orderId = GUIDFactory.createUUID(GUIDType.TYPE_INVITE_CODE).toString();
		}

		return orderId;
	}
	
	/**
	 * 取得邀請碼
	 * @param module
	 * @param sessionID
	 */
	public static void getInviteCode(GameLobbyModule module, GUID sessionID) {
		int messageType = MessageTypes.S_LOBBY_GET_INVITE_CODE_RESPONSE;
		SGetInviteCodeResponse response = new SGetInviteCodeResponse();
		if(module == null){
			response.setErrorCode(ErrorCode.DATA_NOT_FOUND);
			MessageAction.sendMessage(sessionID, messageType , response);
			return;
		}

		GUID playerId = PlayerCommonInfoManager.getInstance().getPlayerGuidBySession(sessionID);
		if(playerId == null){
			response.setErrorCode(ErrorCode.PLAYER_NOT_FOUND);
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		Player playerData = module.getZone().getPlayer(playerId);
		if(playerData == null){
			response.setErrorCode(ErrorCode.NO_PLAYER_DATA);
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		//確認會員邀請碼功能限制
		int limitCode = GameLimitInfo.checkLimitByClassify(GameLimitInfo.PUSH_INVIT_CODE, playerData.getVip(),playerData.getLevel(), playerData.isVerifiedMember(), playerData.isTrialAccount(), playerData.getUplineCode());
		if(limitCode != GameLimitInfo.TRUE){
			response.setErrorCode(GameLimitInfo.limitToErrorCode(limitCode));
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}		
		
		GetInviteCodeDCLAsync async = new GetInviteCodeDCLAsync();
		async.player = playerData;
		async.messageType = messageType;
		async.sessionId = sessionID;
		async.key = playerId;
		module.addAsyncCommand(async);
	}
	
	
	/**
	 * 取得經銷商邀請碼
	 * @param module
	 * @param sessionID
	 */
	public static void getDistributorInviteCode(byte limitCount, GameLobbyModule module, GUID sessionID) {
		int messageType = MessageTypes.S_INVITE_CODE_GET_DISTRIBUTOR_INVITE_CODE_RESPONSE;
		SGetInviteCodeResponse response = new SGetInviteCodeResponse();
		
		if(limitCount < 0) { 
			response.setErrorCode(ErrorCode.INVALID_PARAM);
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		if(module == null){
			response.setErrorCode(ErrorCode.DATA_NOT_FOUND);
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}

		GUID playerId = PlayerCommonInfoManager.getInstance().getPlayerGuidBySession(sessionID);
		if (playerId == null) {
			response.setErrorCode(ErrorCode.PLAYER_NOT_FOUND);
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}

		Player playerData = module.getZone().getPlayer(playerId);
		if (playerData == null) {
			response.setErrorCode(ErrorCode.NO_PLAYER_DATA);
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		//確認會員邀請碼功能限制
		int limitCode = GameLimitInfo.checkLimitByClassify(GameLimitInfo.PUSH_INVIT_CODE, playerData.getVip(),playerData.getLevel(), playerData.isVerifiedMember(), playerData.isTrialAccount(), playerData.getUplineCode());
		if(limitCode != GameLimitInfo.TRUE){
			response.setErrorCode(GameLimitInfo.limitToErrorCode(limitCode));
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		if(playerData.getPlayerIdentityType() == PlayerIdentityType.DOWNLINE || playerData.getPlayerIdentityType() == PlayerIdentityType.NORMAL_PLAYER){
			response.setErrorCode(ErrorCode.DATA_NOT_FOUND);
			MessageAction.sendMessage(sessionID, messageType , response);
			return;
		}
		
		GetDistributorInviteCodeAsync async = new GetDistributorInviteCodeAsync();
		async.player = playerData;
		async.messageType = messageType;
		async.sessionId = sessionID;
		async.key = playerId;
		async.limitCount = limitCount;
		module.addAsyncCommand(async);
	}
	
	/**
	 * 操作阻擋
	 * start 開始 
	 * end 結束 
	 * 請填入時間 24小時制 
	 * EX : 120000  是 12:00:00， 0 是00:00:00 ， 0500 是 00:05:00 ， 183000是 18:30:00
	 * @param start 開始時間 
	 * @param end 結束時間
	 * @return
	 */
	private static boolean modifyBlockByTime(int start,int end) {
		Calendar calendar = Calendar.getInstance();
		int now = calendar.get(Calendar.HOUR_OF_DAY) * 10000 + calendar.get(Calendar.MINUTE) *100 + calendar.get(Calendar.SECOND);
		if (now >= start && now < end) {
			return false;
		}
		return true;
	}
	
	
	/**
	 * 經銷商修改子經銷商的抽傭設定
	 * @param module
	 * @param sessionID
	 */
	public static void modifySubDistributorCommSetting(CModifySubDistributorCommSetting request, GameLobbyModule module, GUID sessionID) {
		int messageType = MessageTypes.S_INVITE_CODE_MODIFY_DISTRIBUTOR_COMM_SETTING_RESPONSE;
		
		SModifySubDistributorCommSettingResponse response = new SModifySubDistributorCommSettingResponse();	

		if(!GameUtility.isHaveString(request.getSubDistributorName())){
			response.setErrorCode(ErrorCode.INVALID_PARAM);
			MessageAction.sendMessage(sessionID, messageType , response);
			return;
		}
		
		if(module == null){
			response.setErrorCode(ErrorCode.DATA_NOT_FOUND);
			MessageAction.sendMessage(sessionID, messageType , response);
			return;
		}

		GUID playerId = PlayerCommonInfoManager.getInstance().getPlayerGuidBySession(sessionID);
		if(playerId == null) {
			response.setErrorCode(ErrorCode.PLAYER_NOT_FOUND);
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		Player playerData = module.getZone().getPlayer(playerId);
		if(playerData == null){
			response.setErrorCode(ErrorCode.NO_PLAYER_DATA);
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		//確認會員邀請碼功能限制
		int limitCode = GameLimitInfo.checkLimitByClassify(GameLimitInfo.PUSH_INVIT_CODE, playerData.getVip(),playerData.getLevel(), playerData.isVerifiedMember(), playerData.isTrialAccount(), playerData.getUplineCode());
		if(limitCode != GameLimitInfo.TRUE){
			response.setErrorCode(GameLimitInfo.limitToErrorCode(limitCode));
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		ModifySubDistributorCommSettingAsync async = new ModifySubDistributorCommSettingAsync();
		async.module = module;
		async.key = playerId;
		async.messageType = messageType;
		async.player = playerData;
		async.subDistributorName = request.getSubDistributorName();
		async.modifyInivteCodeNum = request.getInviteCodeCount();
		async.modifyLevelUpMoney = request.getLevelUpMoney();
		async.modifyDesignatedLevelMoney = request.getDesignatedLeveMoney();
		async.sessionId = sessionID;
		module.addAsyncCommand(async);
		
	}
	
	public static void getSubDistributorsInfo(CGetSubDistributorsInfoRequest request, GameLobbyModule module, GUID sessionID) {
		int messageType = MessageTypes.S_INVITE_CODE_GET_SUB_DISTRIBUTOR_INFO_RESPONSE;
		SGetSubDistributorsInfoResponse response = new SGetSubDistributorsInfoResponse();
		
		if (request.getMaxPerPage() <= 0 || request.getPage() <= 0) {
			response.setErrorCode(ErrorCode.INVALID_PARAM);
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		if (module == null) {
			response.setErrorCode(ErrorCode.DATA_NOT_FOUND);
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}

		GUID playerId = PlayerCommonInfoManager.getInstance().getPlayerGuidBySession(sessionID);
		if (playerId == null) {
			response.setErrorCode(ErrorCode.PLAYER_NOT_FOUND);
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		Player playerData = module.getZone().getPlayer(playerId);
		if (playerData == null) {
			response.setErrorCode(ErrorCode.NO_PLAYER_DATA);
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}

		if (!(playerData.getPlayerIdentityType() == PlayerIdentityType.DISTRIBUTOR || playerData.getPlayerIdentityType() == PlayerIdentityType.BOTH_DISTRIBUTOR_DOWNLINE)) {
			response.setErrorCode(ErrorCode.DATA_NOT_FOUND);
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		GetSubDistributorsInfoAsync async = new GetSubDistributorsInfoAsync();
		async.messageType = messageType;
		async.sessionId = sessionID;
		async.key = playerId;
		async.player = playerData;
		async.page = request.getPage();
		async.maxPerPage = request.getMaxPerPage();
		module.addAsyncCommand(async);
		
	}
	
	/**
	 * 取得所有下線抽傭資訊
	 * @param request
	 * @param module
	 * @param sessionID
	 */
	public static void getDownlineCommInfo(CGetDownlineCommInfoRequest request, GameLobbyModule module, GUID sessionID) {
		int messageType = MessageTypes.S_INVITE_CODE_GET_DOWNLINE_COMM_RESPONSE;
		SGetDownlineCommInfoResponse response = new SGetDownlineCommInfoResponse();
		
		if(!GameUtility.isHaveString(request.getSubDistributorId())) {
			response.setErrorCode(ErrorCode.INVALID_PARAM);
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		GUID subGuid = GUID.parseUUID(request.getSubDistributorId());
		if(subGuid == null){
			response.setErrorCode(ErrorCode.INVALID_PARAM);
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}

		if (request.getMaxPerPage() <= 0 || request.getPage() <= 0) {
			response.setErrorCode(ErrorCode.INVALID_PARAM);
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		if(module == null){
			response.setErrorCode(ErrorCode.DATA_NOT_FOUND);
			MessageAction.sendMessage(sessionID, messageType , response);
			return;
		}

		GUID playerId = PlayerCommonInfoManager.getInstance().getPlayerGuidBySession(sessionID);
		if(playerId == null) {
			response.setErrorCode(ErrorCode.PLAYER_NOT_FOUND);
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		Player playerData = module.getZone().getPlayer(playerId);
		if (playerData == null) {
			response.setErrorCode(ErrorCode.NO_PLAYER_DATA);
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		GetDownlineCommInfoAsync async = new GetDownlineCommInfoAsync();
		async.messageType = messageType;
		async.key = playerId;
		async.player = playerData;
		async.subDistributorGUID = subGuid;
		async.page = request.getPage();
		async.maxPerPage = request.getMaxPerPage();
		async.sessionId = sessionID;
		module.addAsyncCommand(async);
	}
	
	public static void updateSubDistributorCommSetting(){
		DistributorInviteCodeDAO.updateSubDistributorCommSetting();
	}
	
	/**
	 * 檢查玩家身分類型
	 * @param identifyType
	 * @param playerId
	 * @return
	 */
	public static byte playerIdentifyCheck(byte identifyType , String playerId){
		//對經銷商的檢查
		if(identifyType== PlayerIdentityType.DISTRIBUTOR || identifyType == PlayerIdentityType.BOTH_DISTRIBUTOR_DOWNLINE) { 
			//經銷商檢查是否是經銷商&是否開啟設定
			DistributorsModel model = DistributorInviteCodeDAO.getDistributorModelByGUID(playerId);
			if(model == null ||!model.isEffective()){
				identifyType = PlayerIdentityType.NORMAL_PLAYER;
			}
		}else if (identifyType == PlayerIdentityType.SUB_DISTRIBUTOR){
			SubDistributorsModel subDistributorsModel =  DistributorInviteCodeDAO.getSubDistributorsModelByGuid(playerId);
			if (subDistributorsModel == null || subDistributorsModel.getInviteCodeNum() <= 0) {
				identifyType = PlayerIdentityType.NORMAL_PLAYER;
			}else {
				DistributorsModel model = DistributorInviteCodeDAO.getDistributorModelByGUID(subDistributorsModel.getDistributorGuid());
				if(model == null ||!model.isEffective()){
					identifyType = PlayerIdentityType.NORMAL_PLAYER;
				}
			}
		}
		
		return identifyType;
	}
	
	
	
	public static void main(String[] args) {	
		

//		System.setProperty("log4j.configurationFile", "./config/log4j2.xml");
//		InitData.initAll();
//		GUIDFactory.setWorldId(1);
//		GUIDFactory.setProcessId(1);
//		
//		ShardedJedis jedis = JedisManager.getResource(ModuleName.GAMELOBBY);
//		ScanParams params = new ScanParams();
//		params.match("test1*");
//		List<String> aaa = jedis.getShard("").scan("0", params).getResult();
//		xxx.nothing();
		
//		
//		Session session = HibernateManager.txBegin();
//		InviteCodeGroupModel groupModel = new InviteCodeGroupModel();
//		groupModel.setCreateTime(new Date(1483435749000l));
//		groupModel.setEndTime(new Date(1609430400000l));
//		groupModel.setGroupName("網咖店家-推廣卡");
//		groupModel.setGroupId(GUIDFactory.createUUID(GUIDType.TYPE_INVITE_CODE).toString());
//		groupModel.setGoldCoins("[\"30000\"]");
//		groupModel.setTotalCount(16000);
//		groupModel.setType(InviteCodeType.ACTIVITY_SHARE_INVITE_CODE);
//		session.save(groupModel);
//		boolean success = HibernateManager.txCommitFailRollbackClearSession();
//		
//		if(success) {
//			session = HibernateManager.getSession();
//			Query query = session.createQuery("From InviteCodeModel i Where i.notes like '網咖店家-推廣卡%' order by i.createTime asc");
//			ArrayList<InviteCodeModel> aa =(ArrayList<InviteCodeModel>) query.list();
//			HibernateManager.endSession();
//			
//			int i = 1;
//			for (InviteCodeModel model : aa) {
//				model.setSnInGroup(i);
//				model.setGroupId(groupModel.getGroupId());
//				model.setUpperLimit(1);
//				model.setNotes("網咖店家-推廣卡");
//				i++;
//			}
//			
//			session = HibernateManager.txBegin();
//			for (InviteCodeModel inviteCodeModel : aa) {
//				session.update(inviteCodeModel);
//			}
//			HibernateManager.txCommitFailRollbackClearSession();
//		}
		
		
		
		
		
		
		
//		================================================================
//		int size = Integer.valueOf(args[0]);
//		long expiration = Long.valueOf(args[1]);
//		
//		OnMakeActivityInviteCode(size, InviteCodeType.ACTIVITY_SHARE_INVITE_CODE, "網咖店家-推廣卡", expiration);
//		Session session = HibernateLogManager.txBegin();
//		Query query = session.createSQLQuery("select SQL_CALC_FOUND_ROWS playerGUID , s.* from send_gift_record s where (s.playerGUID = :playerID OR s.targetGUID = :playerID) and s.taken = :finish order by s.completeTime desc").addEntity(SendGiftRecordLog.class);
//		
//		query.setParameter("playerID",  "0010040057ebbd04cf6e1948");
//		query.setParameter("finish", true);
//		query.setFirstResult(0);
//		query.setMaxResults(5);
//		ArrayList<SendGiftRecordLog> sendGiftRecordLogs = (ArrayList<SendGiftRecordLog>) query.list();
//
//		query = session.createSQLQuery("SELECT FOUND_ROWS();");
//		Object object = (Object) query.uniqueResult();
//		
//		HibernateLogManager.txCommitFailRollbackClearSession();
		
		//============================================================================
//		int[] column = new int[]{0,0,0,0,0,0,0,0};
//		
//		char keysMap27[] = { 'Q', 'V', 'W', 'A', 'U', 'M', 'F', 'C', 'J', 'T', '3', 'L', '7', 'R',
//			'G', 'Y', 'S', '5', 'D', 'H', '4', '9', 'P', '6', 'X', 'K', 'N' };
//		
//		
//		Session session = HibernateManager.getSession();
//		Query query = session.createQuery("Select inviteCode From InviteCodeModel");
//		List<String> _onlineInviteCodes = (List<String>)query.list();
//		HibernateManager.endSession();
//		HashSet<String> onlineInviteCodes = new HashSet<String>(_onlineInviteCodes);
//		
//		HashSet<String> inviteCodes = new HashSet<String>();
//		Random ran = new Random();
//		
//		session = HibernateManager.getSession();
//		Transaction tx = session.getTransaction();
//		
//		int saveCnt = 0;
//		PreparedInviteCodeModel model = null;
//		while(inviteCodes.size() < 4000000){
//			for (int i = 0; i < column.length; i++) {
//				column[i] = ran.nextInt(27);
//			}
//			
//			if (isConsecutive(column, 2)) {
//				continue;
//			}
//			
//			String inviteCode = Character.toString(keysMap27[column[7]]) + Character.toString(keysMap27[column[6]])+ Character.toString(keysMap27[column[5]])+ Character.toString(keysMap27[column[4]])+ Character.toString(keysMap27[column[3]])+ Character.toString(keysMap27[column[2]])+ Character.toString(keysMap27[column[1]])+ Character.toString(keysMap27[column[0]]);
//			
//			if(isNotRepeating(column,5)){
//				continue;
//			}		
//			
//			if(inviteCodes.contains(inviteCode)){
//				continue;
//			}
//			
//			if(onlineInviteCodes.contains(inviteCode)){
//				continue;
//			}
//			
//
//			inviteCodes.add(inviteCode);	
//			
//			
//			if (saveCnt == 0) {
//				tx.begin();
//			}
//
//			// 存入 log db
//			try {
//				model = new PreparedInviteCodeModel();
//				model.setInviteCode(inviteCode);
//				session.save(model);
//				session.flush();
//
//				// 暫停一下讓出 cpu 資源
//				Thread.sleep(1);
//			} catch (Exception e1) {
//				continue;
//			}
//			
//			saveCnt++;
//			
//			if (saveCnt == 100) {
//				try {
//					tx.commit();
//					session.clear();
//				} catch (HibernateException e) {
//					tx.rollback();
//				}
//				saveCnt = 0;
//			}
//			
//		}
//		
//		HibernateManager.endSession();

//*******************************************************************************//
		
//		System.setProperty("log4j.configurationFile", "./config/log4j2.xml");
//		InitData.initAll();
//		GUIDFactory.setWorldId(1);
//		GUIDFactory.setProcessId(1);
//		
//		
//
//		Session session = HibernateManager.getSession();
//
//		Query query = session.createQuery("From PlayerModel Where level >= 50 and userType = 0");
//		ArrayList<PlayerModel> models = (ArrayList<PlayerModel>) query.list();
//		HibernateManager.endSession();
//		for (PlayerModel playerModel : models) {
//			session = HibernateManager.txBegin();
//			InviteCodeType type = InviteCodeType.NEW_INVITE_CODE;
//			boolean isSingleUse = InviteCodeRewardBinUtil.getInviteCodeInfo(type).isSingleUse();
//			for (int num = 0; num < 3; num++) {
//				
//				String inviteCode = InviteCodeGen.create(type);
//				//System.out.println(inviteCode);
//				try {
//					Thread.sleep(2);
//				} catch (InterruptedException e) {
//					e.printStackTrace();
//				}
//				
//				InviteCodeModel model = new InviteCodeModel();
//				model.setType(type);
//				model.setPlayerId(playerModel.getGuid());
//				model.setInviteCode(inviteCode);
//				model.setExpiration(0);
//				model.setSingleUse(isSingleUse);
//				model.setNotes(type.getNotes());
//				model.setUpperLimit(1);
//				session.save(model);
//			}
//			HibernateManager.txCommitFailRollbackClearSession();
//		}
//		

	}



	
//	public static void OnMakeActivityInviteCode(int size, InviteCodeType inviteCodeType, String note, long expiration) {
//
//		Log log = LogFactory.getLog(InviteCodeProcessor.class);
//		
//		InviteCodeType type = inviteCodeType;
//		
//		String notes = note;
//		notes = notes + ":" + LogDBUtils.getRandomString();
//		expiration = expiration > 0l ? expiration : 0;
//		
//		boolean isSingelUse = InviteCodeRewardBinUtil.getInviteCodeInfo(type).isSingleUse();
//		
//		int upperLimit = isSingelUse ? 0 : 1;
//		
//		Session session = HibernateManager.getSession();
//		Query query = session.createQuery("Select inviteCode From InviteCodeModel where type = :TYPE");
//		query.setParameter("TYPE", type);
//		List<String> onlineCodes = (List<String>)query.list();
//		HibernateManager.endSession();
//		HashSet<String> onlineInviteCodes = new HashSet<String>(onlineCodes);
//		
//		LinkedList<String> inviteCodes = new LinkedList<String>();
//		int inviteCodeLength = type.getTimeLen() + type.getRandomLen();
//		int[] inviteCodeArray = new int[inviteCodeLength];		
//		Random ran = new Random();
//		
//		InviteCodeModel model = null;
//		session = HibernateManager.getSession();
//		Transaction tx = session.getTransaction();
//		int saveCnt = 0;
//		//筆數
//		while(inviteCodes.size() < size){
//			
//			for (int i = 0; i < inviteCodeArray.length; i++) {
//				inviteCodeArray[i] = ran.nextInt(InviteCodeGen.keysMap27.length);
//			}
//			
//			if(isConsecutive(inviteCodeArray, 5)){
//				continue;
//			}
//			
//			if(isNotRepeating(inviteCodeArray, 3)){
//				continue;
//			}
//
//			String inviteCode = getInviteCodeStr(inviteCodeArray);
//			
//			if(inviteCodes.contains(inviteCode)){
//				continue;
//			}
//			
//			if(onlineInviteCodes.contains(inviteCode)){
//				continue;
//			}
//			
//			inviteCodes.add(inviteCode);
//			
//			if (saveCnt == 0) {
//				tx.begin();
//			}
//			
//			try {
//				model = new InviteCodeModel();
//				model.setExpiration(expiration);
//				model.setSingleUse(isSingelUse);
//				model.setUpperLimit(upperLimit);
//				model.setInviteCode(inviteCode);
//				
//				model.setType(type);
//				model.setNotes(notes);
//				
//				session.save(model);
//				session.flush();
//				Thread.sleep(1);
//			} catch (InterruptedException e1) {
//				
//			}
//			saveCnt++;
//
//			if (saveCnt % 100 == 0) {
//				try {
//					tx.commit();
//					session.clear();
//				} catch (HibernateException e) {
//					tx.rollback();
//				}
//				saveCnt = 0;
//			}
//		}
//		
//		if(saveCnt > 0){
//			try {
//				tx.commit();
//				session.clear();
//			} catch (HibernateException e) {
//				tx.rollback();
//			}
//		}
//
//		HibernateManager.endSession();
//		
//		if (log.isInfoEnabled()) {
//			log.info("note = " + notes);
//			for (String inviteCodec : inviteCodes) {
//				log.info(inviteCodec);
//			}
//		}
//	}
//	
//	
//	private static boolean isNotRepeating(int[] column, int length){
//		ArrayList<Integer> testList = new ArrayList<Integer>();
//
//		for (int integer : column) {
//			if (testList.contains(integer)) {
//				continue;
//			}
//			testList.add(integer);
//		}
//
//		if (testList.size() > length) {
//			return false;
//		}
//
//		return true;
//	}
//	
//	private static boolean isConsecutive(int[] column, int length){
//		int count = 0 , num = 0;
//		
//		for (int i = 0; i < column.length; i++) {
//			if(i == 0){
//				num = column[i];
//				count++;
//			} else {
//				if(num == column[i]){
//					count++;
//				}else{
//					num = column[i];
//					count = 1;
//				}
//			}
//			
//			if(count >= length){
//				return true;
//			}
//		}
//		return false;
//	}
//	
//	private static String getInviteCodeStr(int[] inviteCodeArray) {
//		StringBuilder inviteCode = new StringBuilder();
//		for (int num : inviteCodeArray) {
//			inviteCode.append(InviteCodeGen.keysMap27[num]);
//		}
//		return inviteCode.toString().trim();
//	}
}